﻿using Furion.FriendlyException;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using UpperComputer.EntityFramework.Core;
using UpperComputer.WPF.Entry.Common.Extensions;
using UpperComputer.WPF.Entry.Views;
using YFurion;
using YFurion.Exceptions;

namespace UpperComputer.WPF.Entry
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : System.Windows.Application
    {
        private readonly IExceptionHandler _exceptionHandler;

        public App()
        {
            Serve.RunNative(GenericRunOptions.Default
                .AddComponent<YFurionServiceComponent>()
                .AddComponent<UpperComputerEntityFrameworkCoreServiceComponent>()
                .ConfigureBuilder(builder =>
                {
                    builder.UseYFurionSerilogDefault();
                    return builder;
                }));
            _exceptionHandler = Furion.App.GetService<IExceptionHandler>();
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            DispatcherUnhandledException += App_DispatcherUnhandledException;
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
        }

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            LoginWindow loginWindow = Furion.App.GetService<LoginWindow>();
            if (loginWindow.ShowDialog() == true)
            {
                MainWindow mainWindow = Furion.App.GetService<MainWindow>();
                mainWindow.ShowDialog();
            }
            Current.Shutdown();
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception exception = (Exception)e.ExceptionObject;
            _exceptionHandler.OnHandleException(exception, "子线程");
        }

        private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            _exceptionHandler.OnHandleException(e.Exception, "UI线程", HandleFriendlyException);
            e.Handled = true;
        }

        private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            Exception exception = e.Exception.InnerException ?? e.Exception;
            _exceptionHandler.OnHandleException(exception, "异步任务", HandleFriendlyException);
            e.SetObserved();
        }

        private void HandleFriendlyException(AppFriendlyException exception)
        {
            if (Current.MainWindow is MainWindow)
            {
                Entry.MainWindow.Snackbar.ShowErrorMessage(exception.Message);
            }
            else
            {
                if (Dispatcher.Thread != Thread.CurrentThread)
                {
                    Dispatcher.Invoke(() => this.ShowErrorBox(exception.Message));
                }
                else
                {
                    this.ShowErrorBox(exception.Message);
                }
            }
        }
    }
}
